Philosophy, Part One

In this Lecture we won't be doing much coding, but we will be taking a closer look at Pythons ideals, beliefs, and core principles. To do that, let's read a poem together...


In [1]:
import this


The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

In the above we ran one line of code and out popped a poem, and as we go through the course more and more lines of this poem should start to make sense to you. But before all that, let's talk about 'import'.

Import

The Import statement is basically us saying to the computer:

"Hey Python, can you go fetch to other bit of code that someone else wrote? thanx mate."

In this particular case, we are importing something called "this". Python has a few easter-eggs and inside jokes dotted around the place, you can read about the history of how ‘import this’ became a thing by clicking here.

Anyway, the syntax for importing code is below.

import {Name of module we wish to import}

Anyway, I digress; the actual focus of today's lecture is to study the meaning of two lines found within Tim Peter's poem.

  1. Readability counts.
  2. Explicit is better than Implicit.

Part One will speak about readability, part two will talk about the distinction between implicit/explicit code.

Readability counts

On numerous occasions throughout this course I will refer to the idea that readability matters, indeed, we have already seen the importance of good names, but readability has a much larger scope than that. Most of my lectures will focus on how code can made more readable, but in this lecture I want to try to explain why readability counts.

The TLDR version:

  • Readability is at the heart of Python's ethos.
  • Everything else we care about 'flows' from readable code.

The second bullet point is a bit cryptic, but once I’ve finished explaining it will make sense, I promise.

Alright, let’s imagine we are trying to build the ‘perfect’ bit of software. What properties would it have? Its an abstract question, but here are a free of my ideas of what 'perfect code' would look like.

  • it would be performant
  • correct
  • bug free
  • safe (e.g no security defects that could be attacked)
  • easy to use (for the end-user)
  • easy to maintain, improve, change (for programmers)
  • integrates nicely with other code/infrastructure.

So that’s a nice list of qualities that exemplary software would have. The interesting thing to note here is that readability helps with every single one of these bullet points.

Take the first point, performance, how does readability help here?

Well, imagine being handed a novel with all the pages out of order. Think about how much harder and how much more time consuming understanding that novel would be relative to being given a copy with the correct page numbers; working with messy code is very much like the disordered novel. If the code is messy the development team has to spend a lot of time just understanding how the pieces fit together, they have to do that before they can actually go about making meaningful performance improvements. The readable code meanwhile is understood in a much shorter space of time, therefore our team of hypothetical developers can thus spend more of their time and energy focused on the actual task at hand.

In short, the less developers have to wonder about how something works, the more time they have to innervate, tinker, and toy with the code. The result (over long periods of time) is faster code with fewer bugs and more features.

The lesson here is that readability isn’t a ‘nice-to-have extra’, rather, it's a core ingredient for great code. And so, when writing code I want you guys to always ask yourself the following two questions:

  1. Does my code work like it is supposed to? (correctness is the single most important thing, after all).
  2. Can I make my code more readable?

If you keep on asking yourself these two basic questions when writing code then you'll be writing good code in no time at all!

In short, bugs and security flaws often lurk in the shadows. So, one way to avoid these problems is to avoid the number of shadows there are in the first place. In this analogys, the shadows refer to confusing bits of code that are difficult to understand. Complexity obscures things, simplicity reveals the truth.

Here's a quick attempt to show you that.


In [5]:
a = 7
b = (False * a) + a 

c = a / b

So this code is a bit confusing. How can we simplify the code? Well, we can do this:


In [1]:
c = 1

In this above code snippet "False a number" is actually the same as "0 n", which is always zero. So 'b' is always '0 + a', which simplifies to just 'a'. And since 'a' divided by 'a' is always 1 (except when a is zero) we can actually just delete all the code and set c to 1.

Complex code becomes simple. And remember, bugs hide in complexity. We can see that clearly if we set a to zero:


In [4]:
a = 0
b = (False * a) + a 

c = a / b


---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-4-455d8b1f5275> in <module>
      2 b = (False * a) + a
      3 
----> 4 c = a / b

ZeroDivisionError: division by zero

So, not only did simplifying the code make it easier to understand what was going on, the simplification also doesn't contain a zero division error. Its also faster. Okay, I must admit that this example was a bit contrived, but still, hopefully you get the idea; simple code is good, complex code is bad. Okay, lets look at another example:

POP QUIZ! Can you guys figure out what the following code snippet does?


In [ ]:
def f(m, a):
    return m * a

The answer is probably no, and that's not particularly surprising since this code has two new keywords (def, return), indentation, and a few other bits of syntax we have yet to discuss. Tell you what, let's change the variable names to something better and see if you can figure it out then…


In [ ]:
def net_force(mass, acceleration):
    return mass * acceleration

If you have managed to figure out what this code does then I’d say I’ve proven just how useful readability can be; despite you guys not know several bits of syntax a wise choice of variable names allowed you to figure what is (probably) going on.

If I were to rate it, I'd probably give this code a C+. The code seems correct, it is concise, and chose variable names wisely. However, the major drawback to this code is it doesn't use any defensive programming techniques and as a consequence the code may break when we give it unexpected input (the ‘operator overloading’ lecture will go into the specifics). Now, writing code without test cases or checks is acceptable in many cases, but having no tests/checks AND no documentation is just asking for trouble! Basically the problem with the above code is that it makes no effort to warn/protect from 'improper' usage.

What is Defensive Programming?

Defensive programming is a style of writing code whereby you try to write code that ‘predicts’ errors and stops them from happening in the first place.

"Prevention is better than cure".

How can we prevent problems? Well, there are hundreds upon hundreds of ways to do that, but the code snippet above doesn’t try any of them.

That’s it for today, ‘Philosophy part two’ will elaborate even further about some of potential fixes to this code. Stay tuned folks!